home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / me39src2.arc / RANDOM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-08  |  28.2 KB  |  1,061 lines

  1. /*
  2.  * This file contains the command processing functions for a number of random
  3.  * commands. There is no functional grouping here, for sure.
  4.  */
  5.  
  6. #include        <stdio.h>
  7. #include    "estruct.h"
  8. #include        "edef.h"
  9.  
  10. int     tabsize;                        /* Tab size (0: use real tabs)  */
  11.  
  12. /*
  13.  * Set fill column to n.
  14.  */
  15. setfillcol(f, n)
  16. {
  17.         fillcol = n;
  18.     mlwrite("[Fill column is %d]",n);
  19.         return(TRUE);
  20. }
  21.  
  22. /*
  23.  * Display the current position of the cursor, in origin 1 X-Y coordinates,
  24.  * the character that is under the cursor (in hex), and the fraction of the
  25.  * text that is before the cursor. The displayed column is not the current
  26.  * column, but the column that would be used on an infinite width display.
  27.  * Normally this is bound to "C-X =".
  28.  */
  29. showcpos(f, n)
  30. {
  31.         register LINE   *lp;        /* current line */
  32.         register long   numchars;    /* # of chars in file */
  33.         register int    numlines;    /* # of lines in file */
  34.         register long   predchars;    /* # chars preceding point */
  35.         register int    predlines;    /* # lines preceding point */
  36.         register int    curchar;    /* character under cursor */
  37.         int ratio;
  38.         int col;
  39.     int savepos;            /* temp save for current offset */
  40.     int ecol;            /* column pos/end of current line */
  41.  
  42.     /* starting at the beginning of the buffer */
  43.         lp = lforw(curbp->b_linep);
  44.  
  45.     /* start counting chars and lines */
  46.         numchars = 0;
  47.         numlines = 0;
  48.         while (lp != curbp->b_linep) {
  49.         /* if we are on the current line, record it */
  50.         if (lp == curwp->w_dotp) {
  51.             predlines = numlines;
  52.             predchars = numchars + curwp->w_doto;
  53.             if ((curwp->w_doto) == llength(lp))
  54.                 curchar = '\n';
  55.             else
  56.                 curchar = lgetc(lp, curwp->w_doto);
  57.         }
  58.         /* on to the next line */
  59.         ++numlines;
  60.         numchars += llength(lp) + 1;
  61.         lp = lforw(lp);
  62.         }
  63.  
  64.     /* if at end of file, record it */
  65.     if (curwp->w_dotp == curbp->b_linep) {
  66.         predlines = numlines;
  67.         predchars = numchars;
  68.     }
  69.  
  70.     /* Get real column and end-of-line column. */
  71.     col = getccol(FALSE);
  72.     savepos = curwp->w_doto;
  73.     curwp->w_doto = llength(curwp->w_dotp);
  74.     ecol = getccol(FALSE);
  75.     curwp->w_doto = savepos;
  76.  
  77.         ratio = 0;              /* Ratio before dot. */
  78.         if (numchars != 0)
  79.                 ratio = (100L*predchars) / numchars;
  80.  
  81.     /* summarize and report the info */
  82.     mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x",
  83.         predlines+1, numlines+1, col, ecol,
  84.         predchars, numchars, ratio, curchar);
  85.         return (TRUE);
  86. }
  87.  
  88. getcline()    /* get the current line number */
  89.  
  90. {
  91.         register LINE   *lp;        /* current line */
  92.         register int    numlines;    /* # of lines before point */
  93.  
  94.     /* starting at the beginning of the buffer */
  95.         lp = lforw(curbp->b_linep);
  96.  
  97.     /* start counting lines */
  98.         numlines = 0;
  99.         while (lp != curbp->b_linep) {
  100.         /* if we are on the current line, record it */
  101.         if (lp == curwp->w_dotp)
  102.             break;
  103.         ++numlines;
  104.         lp = lforw(lp);
  105.         }
  106.  
  107.     /* and return the resulting count */
  108.     return(numlines + 1);
  109. }
  110.  
  111. /*
  112.  * Return current column.  Stop at first non-blank given TRUE argument.
  113.  */
  114. getccol(bflg)
  115. int bflg;
  116. {
  117.         register int c, i, col;
  118.         col = 0;
  119.         for (i=0; i<curwp->w_doto; ++i) {
  120.                 c = lgetc(curwp->w_dotp, i);
  121.                 if (c!=' ' && c!='\t' && bflg)
  122.                         break;
  123.                 if (c == '\t')
  124.                         col |= 0x07;
  125.                 else if (c<0x20 || c==0x7F)
  126.                         ++col;
  127.                 ++col;
  128.         }
  129.         return(col);
  130. }
  131.  
  132. /*
  133.  * Set current column.
  134.  */
  135. setccol(pos)
  136.  
  137. int pos;    /* position to set cursor */
  138.  
  139. {
  140.         register int c;        /* character being scanned */
  141.     register int i;        /* index into current line */
  142.     register int col;    /* current cursor column   */
  143.     register int llen;    /* length of line in bytes */
  144.  
  145.     col = 0;
  146.     llen = llength(curwp->w_dotp);
  147.  
  148.     /* scan the line until we are at or past the target column */
  149.     for (i = 0; i < llen; ++i) {
  150.         /* upon reaching the target, drop out */
  151.         if (col >= pos)
  152.             break;
  153.  
  154.         /* advance one character */
  155.                 c = lgetc(curwp->w_dotp, i);
  156.                 if (c == '\t')
  157.                         col |= 0x07;
  158.                 else if (c<0x20 || c==0x7F)
  159.                         ++col;
  160.                 ++col;
  161.         }
  162.  
  163.     /* set us at the new position */
  164.     curwp->w_doto = i;
  165.  
  166.     /* and tell weather we made it */
  167.     return(col >= pos);
  168. }
  169.  
  170. /*
  171.  * Twiddle the two characters on either side of dot. If dot is at the end of
  172.  * the line twiddle the two characters before it. Return with an error if dot
  173.  * is at the beginning of line; it seems to be a bit pointless to make this
  174.  * work. This fixes up a very common typo with a single stroke. Normally bound
  175.  * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  176.  */
  177. twiddle(f, n)
  178. {
  179.         register LINE   *dotp;
  180.         register int    doto;
  181.         register int    cl;
  182.         register int    cr;
  183.  
  184.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  185.         return(rdonly());    /* we are in read only mode    */
  186.         dotp = curwp->w_dotp;
  187.         doto = curwp->w_doto;
  188.         if (doto==llength(dotp) && --doto<0)
  189.                 return (FALSE);
  190.         cr = lgetc(dotp, doto);
  191.         if (--doto < 0)
  192.                 return (FALSE);
  193.         cl = lgetc(dotp, doto);
  194.         lputc(dotp, doto+0, cr);
  195.         lputc(dotp, doto+1, cl);
  196.         lchange(WFEDIT);
  197.         return (TRUE);
  198. }
  199.  
  200. /*
  201.  * Quote the next character, and insert it into the buffer. All the characters
  202.  * are taken literally, with the exception of the newline, which always has
  203.  * its line splitting meaning. The character is always read, even if it is
  204.  * inserted 0 times, for regularity. Bound to "C-Q"
  205.  */
  206. quote(f, n)
  207. {
  208.         register int    s;
  209.         register int    c;
  210.  
  211.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  212.         return(rdonly());    /* we are in read only mode    */
  213.         c = tgetc();
  214.         if (n < 0)
  215.                 return (FALSE);
  216.         if (n == 0)
  217.                 return (TRUE);
  218.         if (c == '\n') {
  219.                 do {
  220.                         s = lnewline();
  221.                 } while (s==TRUE && --n);
  222.                 return (s);
  223.         }
  224.         return (linsert(n, c));
  225. }
  226.  
  227. /*
  228.  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  229.  * tab into file.  If given argument, n, of zero, change to true tabs.
  230.  * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  231.  * done in this slightly funny way because the tab (in ASCII) has been turned
  232.  * into "C-I" (in 10 bit code) already. Bound to "C-I".
  233.  */
  234. tab(f, n)
  235. {
  236.         if (n < 0)
  237.                 return (FALSE);
  238.         if (n == 0 || n > 1) {
  239.                 tabsize = n;
  240.                 return(TRUE);
  241.         }
  242.         if (! tabsize)
  243.                 return(linsert(1, '\t'));
  244.         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  245. }
  246.  
  247. #if    AEDIT
  248. detab(f, n)        /* change tabs to spaces */
  249.  
  250. int f,n;    /* default flag and numeric repeat count */
  251.  
  252. {
  253.     register int inc;    /* increment to next line [sgn(n)] */
  254.  
  255.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  256.         return(rdonly());    /* we are in read only mode    */
  257.  
  258.     if (f == FALSE)
  259.         n = 1;
  260.  
  261.     /* loop thru detabbing n lines */
  262.     inc = ((n > 0) ? 1 : -1);
  263.     while (n) {
  264.         curwp->w_doto = 0;    /* start at the beginning */
  265.  
  266.         /* detab the entire current line */
  267.         while (curwp->w_doto < llength(curwp->w_dotp)) {
  268.             /* if we have a tab */
  269.             if (lgetc(curwp->w_dotp, curwp->w_doto) == '\t') {
  270.                 ldelete(1, FALSE);
  271.                 insspace(TRUE, 8 - (curwp->w_doto & 7));
  272.             }
  273.             forwchar(FALSE, 1);
  274.         }
  275.  
  276.         /* advance/or back to the next line */
  277.         forwline(TRUE, inc);
  278.         n -= inc;
  279.     }
  280.     curwp->w_doto = 0;    /* to the begining of the line */
  281.     thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  282.     lchange(WFEDIT);    /* yes, we have made at least an edit */
  283.     return(TRUE);
  284. }
  285.  
  286. entab(f, n)        /* change spaces to tabs where posible */
  287.  
  288. int f,n;    /* default flag and numeric repeat count */
  289.  
  290. {
  291.     register int inc;    /* increment to next line [sgn(n)] */
  292.     register int fspace;    /* pointer to first space if in a run */
  293.     register int ccol;    /* current cursor column */
  294.     register char cchar;    /* current character */
  295.  
  296.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  297.         return(rdonly());    /* we are in read only mode    */
  298.  
  299.     if (f == FALSE)
  300.         n = 1;
  301.  
  302.     /* loop thru entabbing n lines */
  303.     inc = ((n > 0) ? 1 : -1);
  304.     while (n) {
  305.         curwp->w_doto = 0;    /* start at the beginning */
  306.  
  307.         /* entab the entire current line */
  308.         fspace = -1;
  309.         ccol = 0;
  310.         while (curwp->w_doto < llength(curwp->w_dotp)) {
  311.             /* see if it is time to compress */
  312.             if ((fspace >= 0) && (nextab(fspace) <= ccol))
  313.                 if (ccol - fspace < 2)
  314.                     fspace = -1;
  315.                 else {
  316.         /* there is a bug here dealing with mixed space/tabed
  317.            lines.......it will get fixed        */
  318.                     backchar(TRUE, ccol - fspace);
  319.                     ldelete(ccol - fspace, FALSE);
  320.                     linsert(1, '\t');    
  321.                     fspace = -1;
  322.                 }
  323.  
  324.             /* get the current character */
  325.             cchar = lgetc(curwp->w_dotp, curwp->w_doto);
  326.  
  327.             switch (cchar) {
  328.                 case '\t': /* a tab...count em up */
  329.                     ccol = nextab(ccol);
  330.                     break;
  331.  
  332.                 case ' ':  /* a space...compress? */
  333.                     if (fspace == -1)
  334.                         fspace = ccol;
  335.                     ccol++;
  336.                     break;
  337.  
  338.                 default:   /* any other char...just count */
  339.                     ccol++;
  340.                     fspace = -1;
  341.                     break;
  342.             }
  343.             forwchar(FALSE, 1);
  344.         }
  345.  
  346.         /* advance/or back to the next line */
  347.         forwline(TRUE, inc);
  348.         n -= inc;
  349.     }
  350.     curwp->w_doto = 0;    /* to the begining of the line */
  351.     thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  352.     lchange(WFEDIT);    /* yes, we have made at least an edit */
  353.     return(TRUE);
  354. }
  355.  
  356. trim(f, n)    /* trim trailing whitespace from the point to eol */
  357.  
  358. int f,n;    /* default flag and numeric repeat count */
  359.  
  360. {
  361.     register LINE *lp;    /* current line pointer */
  362.     register int offset;    /* original line offset position */
  363.     register int length;    /* current length */
  364.     register int inc;    /* increment to next line [sgn(n)] */
  365.  
  366.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  367.         return(rdonly());    /* we are in read only mode    */
  368.  
  369.     if (f == FALSE)
  370.         n = 1;
  371.  
  372.     /* loop thru trimming n lines */
  373.     inc = ((n > 0) ? 1 : -1);
  374.     while (n) {
  375.         lp = curwp->w_dotp;        /* find current line text */
  376.         offset = curwp->w_doto;        /* save original offset */
  377.         length = lp->l_used;        /* find current length */
  378.  
  379.         /* trim the current line */
  380.         while (length > offset) {
  381.             if (lgetc(lp, length-1) != ' ' &&
  382.                 lgetc(lp, length-1) != '\t')
  383.                     break;
  384.             length--;
  385.         }
  386.         lp->l_used = length;
  387.  
  388.         /* advance/or back to the next line */
  389.         forwline(TRUE, inc);
  390.         n -= inc;
  391.     }
  392.     lchange(WFEDIT);
  393.     thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  394.     return(TRUE);
  395. }
  396. #endif
  397.  
  398. /*
  399.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  400.  * and then back up over them. Everything is done by the subcommand
  401.  * procerssors. They even handle the looping. Normally this is bound to "C-O".
  402.  */
  403. openline(f, n)
  404. {
  405.         register int    i;
  406.         register int    s;
  407.  
  408.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  409.         return(rdonly());    /* we are in read only mode    */
  410.         if (n < 0)
  411.                 return (FALSE);
  412.         if (n == 0)
  413.                 return (TRUE);
  414.         i = n;                                  /* Insert newlines.     */
  415.         do {
  416.                 s = lnewline();
  417.         } while (s==TRUE && --i);
  418.         if (s == TRUE)                          /* Then back up overtop */
  419.                 s = backchar(f, n);             /* of them all.         */
  420.         return (s);
  421. }
  422.  
  423. /*
  424.  * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
  425.  * indentation as specified.
  426.  */
  427. newline(f, n)
  428. {
  429.     register int    s;
  430.  
  431.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  432.         return(rdonly());    /* we are in read only mode    */
  433.     if (n < 0)
  434.         return (FALSE);
  435.  
  436.     /* if we are in C mode and this is a default <NL> */
  437.     if (n == 1 && (curbp->b_mode & MDCMOD) &&
  438.         curwp->w_dotp != curbp->b_linep)
  439.         return(cinsert());
  440.  
  441.         /*
  442.          * If a newline was typed, fill column is defined, the argument is non-
  443.          * negative, wrap mode is enabled, and we are now past fill column,
  444.      * and we are not read-only, perform word wrap.
  445.          */
  446.         if ((curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  447.         getccol(FALSE) > fillcol &&
  448.         (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
  449.         execute(META|SPEC|'W', FALSE, 1);
  450.  
  451.     /* insert some lines */
  452.     while (n--) {
  453.         if ((s=lnewline()) != TRUE)
  454.             return (s);
  455.     }
  456.     return (TRUE);
  457. }
  458.  
  459. cinsert()    /* insert a newline and indentation for C */
  460.  
  461. {
  462.     register char *cptr;    /* string pointer into text to copy */
  463.     register int tptr;    /* index to scan into line */
  464.     register int bracef;    /* was there a brace at the end of line? */
  465.     register int i;
  466.     char ichar[NSTRING];    /* buffer to hold indent of last line */
  467.  
  468.     /* grab a pointer to text to copy indentation from */
  469.     cptr = &curwp->w_dotp->l_text[0];
  470.  
  471.     /* check for a brace */
  472.     tptr = curwp->w_doto - 1;
  473.     bracef = (cptr[tptr] == '{');
  474.  
  475.     /* save the indent of the previous line */
  476.     i = 0;
  477.     while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
  478.         && (i < NSTRING - 1)) {
  479.         ichar[i] = cptr[i];
  480.         ++i;
  481.     }
  482.     ichar[i] = 0;        /* terminate it */
  483.  
  484.     /* put in the newline */
  485.     if (lnewline() == FALSE)
  486.         return(FALSE);
  487.  
  488.     /* and the saved indentation */
  489.     i = 0;
  490.     while (ichar[i])
  491.         linsert(1, ichar[i++]);
  492.  
  493.     /* and one more tab for a brace */
  494.     if (bracef)
  495.         tab(FALSE, 1);
  496.  
  497.     return(TRUE);
  498. }
  499.  
  500. insbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  501.  
  502. int n;    /* repeat count */
  503. int c;    /* brace to insert (always { for now) */
  504.  
  505. {
  506.     register int ch;    /* last character before input */
  507.     register int i;
  508.     register int target;    /* column brace should go after */
  509.  
  510.     /* if we are at the beginning of the line, no go */
  511.     if (curwp->w_doto == 0)
  512.         return(linsert(n,c));
  513.  
  514.     /* scan to see if all space before this is white space */
  515.     for (i = curwp->w_doto - 1; i >= 0; --i) {
  516.         ch = lgetc(curwp->w_dotp, i);
  517.         if (ch != ' ' && ch != '\t')
  518.             return(linsert(n, c));
  519.     }
  520.  
  521.     /* delete back first */
  522.     target = getccol(FALSE);    /* calc where we will delete to */
  523.     target -= 1;
  524.     target -= target % (tabsize == 0 ? 8 : tabsize);
  525.     while (getccol(FALSE) > target)
  526.         backdel(FALSE, 1);
  527.  
  528.     /* and insert the required brace(s) */
  529.     return(linsert(n, c));
  530. }
  531.  
  532. inspound()    /* insert a # into the text here...we are in CMODE */
  533.  
  534. {
  535.     register int ch;    /* last character before input */
  536.     register int i;
  537.  
  538.     /* if we are at the beginning of the line, no go */
  539.     if (curwp->w_doto == 0)
  540.         return(linsert(1,'#'));
  541.  
  542.     /* scan to see if all space before this is white space */
  543.     for (i = curwp->w_doto - 1; i >= 0; --i) {
  544.         ch = lgetc(curwp->w_dotp, i);
  545.         if (ch != ' ' && ch != '\t')
  546.             return(linsert(1, '#'));
  547.     }
  548.  
  549.     /* delete back first */
  550.     while (getccol(FALSE) >= 1)
  551.         backdel(FALSE, 1);
  552.  
  553.     /* and insert the required pound */
  554.     return(linsert(1, '#'));
  555. }
  556.  
  557. /*
  558.  * Delete blank lines around dot. What this command does depends if dot is
  559.  * sitting on a blank line. If dot is sitting on a blank line, this command
  560.  * deletes all the blank lines above and below the current line. If it is
  561.  * sitting on a non blank line then it deletes all of the blank lines after
  562.  * the line. Normally this command is bound to "C-X C-O". Any argument is
  563.  * ignored.
  564.  */
  565. deblank(f, n)
  566. {
  567.         register LINE   *lp1;
  568.         register LINE   *lp2;
  569.         long nld;
  570.  
  571.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  572.         return(rdonly());    /* we are in read only mode    */
  573.         lp1 = curwp->w_dotp;
  574.         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  575.                 lp1 = lp2;
  576.         lp2 = lp1;
  577.         nld = 0;
  578.         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  579.                 ++nld;
  580.         if (nld == 0)
  581.                 return (TRUE);
  582.         curwp->w_dotp = lforw(lp1);
  583.         curwp->w_doto = 0;
  584.         return (ldelete(nld, FALSE));
  585. }
  586.  
  587. /*
  588.  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  589.  * of the previous line. Assumes tabs are every eight characters. Quite simple.
  590.  * Figure out the indentation of the current line. Insert a newline by calling
  591.  * the standard routine. Insert the indentation by inserting the right number
  592.  * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  593.  * subcomands failed. Normally bound to "C-J".
  594.  */
  595. indent(f, n)
  596. {
  597.         register int    nicol;
  598.         register int    c;
  599.         register int    i;
  600.  
  601.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  602.         return(rdonly());    /* we are in read only mode    */
  603.         if (n < 0)
  604.                 return (FALSE);
  605.         while (n--) {
  606.                 nicol = 0;
  607.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  608.                         c = lgetc(curwp->w_dotp, i);
  609.                         if (c!=' ' && c!='\t')
  610.                                 break;
  611.                         if (c == '\t')
  612.                                 nicol |= 0x07;
  613.                         ++nicol;
  614.                 }
  615.                 if (lnewline() == FALSE
  616.                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  617.                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  618.                         return (FALSE);
  619.         }
  620.         return (TRUE);
  621. }
  622.  
  623. /*
  624.  * Delete forward. This is real easy, because the basic delete routine does
  625.  * all of the work. Watches for negative arguments, and does the right thing.
  626.  * If any argument is present, it kills rather than deletes, to prevent loss
  627.  * of text if typed with a big argument. Normally bound to "C-D".
  628.  */
  629. forwdel(f, n)
  630. {
  631.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  632.         return(rdonly());    /* we are in read only mode    */
  633.         if (n < 0)
  634.                 return (backdel(f, -n));
  635.         if (f != FALSE) {                       /* Really a kill.       */
  636.                 if ((lastflag&CFKILL) == 0)
  637.                         kdelete();
  638.                 thisflag |= CFKILL;
  639.         }
  640.         return (ldelete((long)n, f));
  641. }
  642.  
  643. /*
  644.  * Delete backwards. This is quite easy too, because it's all done with other
  645.  * functions. Just move the cursor back, and delete forwards. Like delete
  646.  * forward, this actually does a kill if presented with an argument. Bound to
  647.  * both "RUBOUT" and "C-H".
  648.  */
  649. backdel(f, n)
  650. {
  651.         register int    s;
  652.  
  653.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  654.         return(rdonly());    /* we are in read only mode    */
  655.         if (n < 0)
  656.                 return (forwdel(f, -n));
  657.         if (f != FALSE) {                       /* Really a kill.       */
  658.                 if ((lastflag&CFKILL) == 0)
  659.                         kdelete();
  660.                 thisflag |= CFKILL;
  661.         }
  662.         if ((s=backchar(f, n)) == TRUE)
  663.                 s = ldelete((long)n, f);
  664.         return (s);
  665. }
  666.  
  667. /*
  668.  * Kill text. If called without an argument, it kills from dot to the end of
  669.  * the line, unless it is at the end of the line, when it kills the newline.
  670.  * If called with an argument of 0, it kills from the start of the line to dot.
  671.  * If called with a positive argument, it kills from dot forward over that
  672.  * number of newlines. If called with a negative argument it kills backwards
  673.  * that number of newlines. Normally bound to "C-K".
  674.  */
  675. killtext(f, n)
  676. {
  677.         register LINE   *nextp;
  678.         long chunk;
  679.  
  680.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  681.         return(rdonly());    /* we are in read only mode    */
  682.         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  683.                 kdelete();                      /* last wasn't a kill.  */
  684.         thisflag |= CFKILL;
  685.         if (f == FALSE) {
  686.                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
  687.                 if (chunk == 0)
  688.                         chunk = 1;
  689.         } else if (n == 0) {
  690.                 chunk = curwp->w_doto;
  691.                 curwp->w_doto = 0;
  692.         } else if (n > 0) {
  693.                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  694.                 nextp = lforw(curwp->w_dotp);
  695.                 while (--n) {
  696.                         if (nextp == curbp->b_linep)
  697.                                 return (FALSE);
  698.                         chunk += llength(nextp)+1;
  699.                         nextp = lforw(nextp);
  700.                 }
  701.         } else {
  702.                 mlwrite("neg kill");
  703.                 return (FALSE);
  704.         }
  705.         return(ldelete(chunk, TRUE));
  706. }
  707.  
  708. setmode(f, n)    /* prompt and set an editor mode */
  709.  
  710. int f, n;    /* default and argument */
  711.  
  712. {
  713.     adjustmode(TRUE, FALSE);
  714. }
  715.  
  716. delmode(f, n)    /* prompt and delete an editor mode */
  717.  
  718. int f, n;    /* default and argument */
  719.  
  720. {
  721.     adjustmode(FALSE, FALSE);
  722. }
  723.  
  724. setgmode(f, n)    /* prompt and set a global editor mode */
  725.  
  726. int f, n;    /* default and argument */
  727.  
  728. {
  729.     adjustmode(TRUE, TRUE);
  730. }
  731.  
  732. delgmode(f, n)    /* prompt and delete a global editor mode */
  733.  
  734. int f, n;    /* default and argument */
  735.  
  736. {
  737.     adjustmode(FALSE, TRUE);
  738. }
  739.  
  740. adjustmode(kind, global)    /* change the editor mode status */
  741.  
  742. int kind;    /* true = set,        false = delete */
  743. int global;    /* true = global flag,    false = current buffer flag */
  744. {
  745.     register char *scan;        /* scanning pointer to convert prompt */
  746.     register int i;            /* loop index */
  747.     register status;        /* error return on input */
  748. #if    COLOR
  749.     register int uflag;        /* was modename uppercase?    */
  750. #endif
  751.     char prompt[50];    /* string to prompt user with */
  752.     char cbuf[NPAT];        /* buffer to recieve mode name into */
  753.  
  754.     /* build the proper prompt string */
  755.     if (global)
  756.         strcpy(prompt,"Global mode to ");
  757.     else
  758.         strcpy(prompt,"Mode to ");
  759.  
  760.     if (kind == TRUE)
  761.         strcat(prompt, "add: ");
  762.     else
  763.         strcat(prompt, "delete: ");
  764.  
  765.     /* prompt the user and get an answer */
  766.  
  767.     status = mlreply(prompt, cbuf, NPAT - 1);
  768.     if (status != TRUE)
  769.         return(status);
  770.  
  771.     /* make it uppercase */
  772.  
  773.     scan = cbuf;
  774. #if    COLOR
  775.     uflag = (*scan >= 'A' && *scan <= 'Z');
  776. #endif
  777.     while (*scan != 0) {
  778.         if (*scan >= 'a' && *scan <= 'z')
  779.             *scan = *scan - 32;
  780.         scan++;
  781.     }
  782.  
  783.     /* test it first against the colors we know */
  784.     for (i=0; i<NCOLORS; i++) {
  785.         if (strcmp(cbuf, cname[i]) == 0) {
  786.             /* finding the match, we set the color */
  787. #if    COLOR
  788.             if (uflag)
  789.                 if (global)
  790.                     gfcolor = i;
  791.                 else
  792.                     curwp->w_fcolor = i;
  793.             else
  794.                 if (global)
  795.                     gbcolor = i;
  796.                 else
  797.                     curwp->w_bcolor = i;
  798.  
  799.             curwp->w_flag |= WFCOLR;
  800. #endif
  801.             mlerase();
  802.             return(TRUE);
  803.         }
  804.     }
  805.  
  806.     /* test it against the modes we know */
  807.  
  808.     for (i=0; i < NUMMODES; i++) {
  809.         if (strcmp(cbuf, modename[i]) == 0) {
  810.             /* finding a match, we process it */
  811.             if (kind == TRUE)
  812.                 if (global)
  813.                     gmode |= (1 << i);
  814.                 else
  815.                     curbp->b_mode |= (1 << i);
  816.             else
  817.                 if (global)
  818.                     gmode &= ~(1 << i);
  819.                 else
  820.                     curbp->b_mode &= ~(1 << i);
  821.             /* display new mode line */
  822.             if (global == 0)
  823.                 upmode();
  824.             mlerase();    /* erase the junk */
  825.             return(TRUE);
  826.         }
  827.     }
  828.  
  829.     mlwrite("No such mode!");
  830.     return(FALSE);
  831. }
  832.  
  833. /*    This function simply clears the message line,
  834.         mainly for macro usage            */
  835.  
  836. clrmes(f, n)
  837.  
  838. int f, n;    /* arguments ignored */
  839.  
  840. {
  841.     mlforce("");
  842.     return(TRUE);
  843. }
  844.  
  845. /*    This function writes a string on the message line
  846.         mainly for macro usage            */
  847.  
  848. writemsg(f, n)
  849.  
  850. int f, n;    /* arguments ignored */
  851.  
  852. {
  853.     register char *sp;    /* pointer into buf to expand %s */
  854.     register char *np;    /* ptr into nbuf */
  855.     register int status;
  856.     char buf[NPAT];        /* buffer to recieve message into */
  857.     char nbuf[NPAT*2];    /* buffer to expand string into */
  858.  
  859.     if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE)
  860.         return(status);
  861.  
  862.     /* expand all '%' to "%%" so mlwrite won't expect arguments */
  863.     sp = buf;
  864.     np = nbuf;
  865.     while (*sp) {
  866.         *np++ = *sp;
  867.         if (*sp++ == '%')
  868.             *np++ = '%';
  869.     }
  870.     *np = '\0';
  871.  
  872.     /* write the message out */
  873.     mlforce(nbuf);
  874.     return(TRUE);
  875. }
  876.  
  877. #if    CFENCE
  878. /*    the cursor is moved to a matching fence    */
  879.  
  880. getfence(f, n)
  881.  
  882. int f, n;    /* not used */
  883.  
  884. {
  885.     register LINE *oldlp;    /* original line pointer */
  886.     register int oldoff;    /* and offset */
  887.     register int sdir;    /* direction of search (1/-1) */
  888.     register int count;    /* current fence level count */
  889.     register char ch;    /* fence type to match against */
  890.     register char ofence;    /* open fence */
  891.     register char c;    /* current character in scan */
  892.  
  893.     /* save the original cursor position */
  894.     oldlp = curwp->w_dotp;
  895.     oldoff = curwp->w_doto;
  896.  
  897.     /* get the current character */
  898.     if (oldoff == llength(oldlp))
  899.         ch = '\n';
  900.     else
  901.         ch = lgetc(oldlp, oldoff);
  902.  
  903.     /* setup proper matching fence */
  904.     switch (ch) {
  905.         case '(': ofence = ')'; sdir = FORWARD; break;
  906.         case '{': ofence = '}'; sdir = FORWARD; break;
  907.         case '[': ofence = ']'; sdir = FORWARD; break;
  908.         case ')': ofence = '('; sdir = REVERSE; break;
  909.         case '}': ofence = '{'; sdir = REVERSE; break;
  910.         case ']': ofence = '['; sdir = REVERSE; break;
  911.         default: TTbeep(); return(FALSE);
  912.     }
  913.  
  914.     /* set up for scan */
  915.     count = 1;
  916.     if (sdir == REVERSE)
  917.         backchar(FALSE, 1);
  918.     else
  919.         forwchar(FALSE, 1);
  920.  
  921.     /* scan until we find it, or reach the end of file */
  922.     while (count > 0) {
  923.         if (curwp->w_doto == llength(curwp->w_dotp))
  924.             c = '\n';
  925.         else
  926.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  927.         if (c == ch)
  928.             ++count;
  929.         if (c == ofence)
  930.             --count;
  931.         if (sdir == FORWARD)
  932.             forwchar(FALSE, 1);
  933.         else
  934.             backchar(FALSE, 1);
  935.         if (boundry(curwp->w_dotp, curwp->w_doto, sdir))
  936.             break;
  937.     }
  938.  
  939.     /* if count is zero, we have a match, move the sucker */
  940.     if (count == 0) {
  941.         if (sdir == FORWARD)
  942.             backchar(FALSE, 1);
  943.         else
  944.             forwchar(FALSE, 1);
  945.         curwp->w_flag |= WFMOVE;
  946.         return(TRUE);
  947.     }
  948.  
  949.     /* restore the current position */
  950.     curwp->w_dotp = oldlp;
  951.     curwp->w_doto = oldoff;
  952.     TTbeep();
  953.     return(FALSE);
  954. }
  955. #endif
  956.  
  957. /*    Close fences are matched against their partners, and if
  958.     on screen the cursor briefly lights there        */
  959.  
  960. fmatch(ch)
  961.  
  962. char ch;    /* fence type to match against */
  963.  
  964. {
  965.     register LINE *oldlp;    /* original line pointer */
  966.     register int oldoff;    /* and offset */
  967.     register LINE *toplp;    /* top line in current window */
  968.     register int count;    /* current fence level count */
  969.     register char opench;    /* open fence */
  970.     register char c;    /* current character in scan */
  971.     register int i;
  972.  
  973.     /* first get the display update out there */
  974.     update(FALSE);
  975.  
  976.     /* save the original cursor position */
  977.     oldlp = curwp->w_dotp;
  978.     oldoff = curwp->w_doto;
  979.  
  980.     /* setup proper open fence for passed close fence */
  981.     if (ch == ')')
  982.         opench = '(';
  983.     else if (ch == '}')
  984.         opench = '{';
  985.     else
  986.         opench = '[';
  987.  
  988.     /* find the top line and set up for scan */
  989.     toplp = curwp->w_linep->l_bp;
  990.     count = 1;
  991.     backchar(FALSE, 2);
  992.  
  993.     /* scan back until we find it, or reach past the top of the window */
  994.     while (count > 0 && curwp->w_dotp != toplp) {
  995.         if (curwp->w_doto == llength(curwp->w_dotp))
  996.             c = '\n';
  997.         else
  998.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  999.         if (c == ch)
  1000.             ++count;
  1001.         if (c == opench)
  1002.             --count;
  1003.         backchar(FALSE, 1);
  1004.         if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp &&
  1005.             curwp->w_doto == 0)
  1006.             break;
  1007.     }
  1008.  
  1009.     /* if count is zero, we have a match, display the sucker */
  1010.     /* there is a real machine dependant timing problem here we have
  1011.        yet to solve......... */
  1012.     if (count == 0) {
  1013.         forwchar(FALSE, 1);
  1014.         for (i = 0; i < term.t_pause; i++)
  1015.             update(FALSE);
  1016.     }
  1017.  
  1018.     /* restore the current position */
  1019.     curwp->w_dotp = oldlp;
  1020.     curwp->w_doto = oldoff;
  1021.     return(TRUE);
  1022. }
  1023.  
  1024. istring(f, n)    /* ask for and insert a string into the current
  1025.            buffer at the current point */
  1026.  
  1027. int f, n;    /* ignored arguments */
  1028.  
  1029. {
  1030.     register char *tp;    /* pointer into string to add */
  1031.     register int status;    /* status return code */
  1032.     char tstring[NPAT+1];    /* string to add */
  1033.  
  1034.     /* ask for string to insert */
  1035.     status = mlreplyt("String to insert<META>: ", tstring, NPAT, metac);
  1036.     if (status != TRUE)
  1037.         return(status);
  1038.  
  1039.     if (f == FALSE)
  1040.         n = 1;
  1041.  
  1042.     if (n < 0)
  1043.         n = - n;
  1044.  
  1045.     /* insert it */
  1046.     while (n--) {
  1047.         tp = &tstring[0];
  1048.         while (*tp) {
  1049.             if (*tp == 0x0a)
  1050.                 status = lnewline();
  1051.             else
  1052.                 status = linsert(1, *tp);
  1053.             ++tp;
  1054.             if (status != TRUE)
  1055.                 return(status);
  1056.         }
  1057.     }
  1058.  
  1059.     return(TRUE);
  1060. }
  1061.